using System;
using L=Science.Physics.GeneralPhysics;

namespace Serway.Chapter05
{
	/// <summary>
	/// Example14: Acceleration of Two Connected Objects When Friction is present
	/// A block of mass m_1 on a roght, horizontal surface is 
	/// connected to a ball of mass m_2 by a lightweight cord
	/// over a lightweight, frictionless pulley. A force of 
	/// magnitude F at an angle \theta with the horizontal is
	/// applied to the block. The coefficient of kinetic
	/// friction between the block and surface is \mu_k. Determine
	/// the magnitude of the acceleration of the two objects.
	/// a = {F(\cos\theta + \mu_k \sin\theta)-g(m_2+\mu_k m_1)}/(m_1+m_2)
	/// </summary>
	public class Example14
	{
		public Example14()
		{
		}
		private string result;
		public string Result
		{
			get{return result;}
		}

		private double theta = 35.0/180.0*Math.PI;
		private double muk = 0.2;
		private double F = 50.0;
		private double m1 = 10.0;
		private double m2 = 1.0;

		public void Compute()  
		{
			L.TotalForce[] f = new L.TotalForce[2]; 
			L.Mass[] m = new L.Mass[2];
			L.Acceleration[] a = new L.Acceleration[2];

			m[0]= new L.Mass();  // block
			m[0].kg = m1;
			m[1]= new L.Mass();  // ball
			m[1].kg = m2;
			
			L.Force[] sf = new L.Force[5];  // forces on block
			sf[0] = new L.Force();  // tension
			sf[0].XVariableQ = true;
			sf[1] = new L.Force();  // gravity
			sf[1].Y = -m[0].kg*L.Constant.AccelerationOfGravity;
			sf[2] = new L.Force();  // normal
			sf[2].YVariableQ = true;
			sf[3] = new L.Force();  // friction
			sf[3].XVariableQ = true;
			sf[4] = new L.Force();  // applied force
			sf[4].X = F*Math.Cos(theta);
			sf[4].Y = F*Math.Sin(theta);		
		
			f[0] = new L.TotalForce(sf);	

			L.Force[] ff = new L.Force[2];
			ff[0] = new L.Force();   // tension
			ff[0].YVariableQ = true; 
			ff[1] = new L.Force();   // gravity
			ff[1].Y = -m[1].kg*L.Constant.AccelerationOfGravity; 

			f[1] = new L.TotalForce(ff);					
			
			a[0] = new L.Acceleration();
			a[0].XVariableQ = true; 
			a[1] = new L.Acceleration();
			a[1].YVariableQ = true; 

			L.NewtonEquation.ConstraintFunctionToBeZero[] cf
				= new L.NewtonEquation.ConstraintFunctionToBeZero[4];
			cf[0] = new L.NewtonEquation.ConstraintFunctionToBeZero(Min1);
			cf[1] = new L.NewtonEquation.ConstraintFunctionToBeZero(Min2);
			cf[2] = new L.NewtonEquation.ConstraintFunctionToBeZero(Min3);
			cf[3] = new L.NewtonEquation.ConstraintFunctionToBeZero(Min4);
			
			L.NewtonEquation eq = new L.NewtonEquation(f,m,a);			
			eq.Constraint(cf);

			eq.Solve();
		
			result += Convert.ToString(a[0].X)+"\r\n";
			result += Convert.ToString(
				(50.0*(Math.Cos(theta) + muk*Math.Sin(theta))
				-L.Constant.AccelerationOfGravity*(m[1].kg + muk*m[0].kg))
				/(m[1].kg+m[0].kg)
				)+"\r\n";
		}
		private double Min1(L.TotalForce[] f, L.Mass[] m, L.Acceleration[] a)
		{
			return f[0].DecomposedForce[0].X + f[1].DecomposedForce[0].Y;
		}
		private double Min2(L.TotalForce[] f, L.Mass[] m, L.Acceleration[] a)
		{
			return f[0].DecomposedForce[1].Y + f[0].DecomposedForce[2].Y
				 + f[0].DecomposedForce[4].Y;
		}
		private double Min3(L.TotalForce[] f, L.Mass[] m, L.Acceleration[] a)
		{
			return muk*f[0].DecomposedForce[2].Y + f[0].DecomposedForce[3].X;
		}
		private double Min4(L.TotalForce[] f, L.Mass[] m, L.Acceleration[] a)
		{
			return a[0].X - a[1].Y;
		}		
	}
}
